#!/usr/bin/env python3
"""
Android API 辅助库 - 用于在Python中调用Android代码并获取返回值

使用方法:
    from android_api import AndroidAPI
    
    api = AndroidAPI()
    
    # 调用Android代码并获取返回值
    result = api.call_android("get_device_info")
    if result['status'] == 'success':
        print(result['data'])
    
    # 带参数调用
    result = api.call_android("calculate", data="10+5")
    print(result['data'])  # 输出: 15.0
"""

import subprocess
import os
import json
import time
import uuid
from pathlib import Path


class AndroidAPI:
    """Android API调用类"""
    
    # Android广播接收器的组件名
    RECEIVER_COMPONENT = "com.termux/.app.api.PythonApiReceiver"
    ACTION = "com.termux.PYTHON_API"
    
    # 返回值存储目录（相对于HOME目录）
    RESULT_DIR = "python_api_results"
    
    def __init__(self, timeout=5.0, result_dir=None):
        """
        初始化Android API客户端
        
        Args:
            timeout: 等待返回值的超时时间（秒）
            result_dir: 返回值存储目录，如果为None则使用默认目录
        """
        self.timeout = timeout
        self.home_dir = os.path.expanduser("~")
        
        if result_dir is None:
            self.result_dir = os.path.join(self.home_dir, self.RESULT_DIR)
        else:
            self.result_dir = result_dir
        
        # 确保结果目录存在
        os.makedirs(self.result_dir, exist_ok=True)
    
    def _generate_result_id(self):
        """生成唯一的结果ID"""
        return str(uuid.uuid4())
    
    def _get_result_file_path(self, result_id):
        """获取结果文件路径"""
        return os.path.join(self.result_dir, f"{result_id}.json")
    
    def _wait_for_result(self, result_id, timeout=None):
        """
        等待并读取返回值
        
        Args:
            result_id: 结果ID
            timeout: 超时时间（秒），如果为None则使用self.timeout
            
        Returns:
            dict: 包含status和data的字典，如果超时或出错则返回None
        """
        if timeout is None:
            timeout = self.timeout
        
        result_file = self._get_result_file_path(result_id)
        start_time = time.time()
        
        # 轮询等待结果文件出现
        while time.time() - start_time < timeout:
            if os.path.exists(result_file):
                try:
                    # 读取结果文件
                    with open(result_file, 'r', encoding='utf-8') as f:
                        content = f.read().strip()
                    
                    # 解析JSON
                    result = json.loads(content)
                    
                    # 清理结果文件
                    try:
                        os.remove(result_file)
                    except:
                        pass
                    
                    return result
                except json.JSONDecodeError as e:
                    print(f"解析返回值JSON失败: {e}")
                    return {"status": "error", "data": f"JSON解析错误: {e}"}
                except Exception as e:
                    print(f"读取返回值失败: {e}")
                    return {"status": "error", "data": f"读取错误: {e}"}
            
            # 短暂休眠，避免CPU占用过高
            time.sleep(0.1)
        
        # 超时
        return {"status": "error", "data": "等待返回值超时"}
    
    def call_android(self, action, message=None, title=None, data=None, 
                     wait_result=True, timeout=None):
        """
        调用Android代码
        
        Args:
            action: 要执行的操作（如 "show_toast", "get_device_info", "calculate" 等）
            message: 消息内容（可选）
            title: 标题（可选）
            data: 数据内容（可选）
            wait_result: 是否等待返回值，如果为False则只发送广播不等待
            timeout: 超时时间（秒），如果为None则使用self.timeout
            
        Returns:
            dict: 如果wait_result为True，返回包含status和data的字典
                  如果wait_result为False，返回None
        """
        # 检查 am 命令是否可用
        import shutil
        am_path = shutil.which("am")
        if not am_path:
            return {
                "status": "error",
                "data": "am 命令未找到。请安装: pkg install termux-tools"
            }
        
        # 测试 am 命令是否能正常工作（实际测试广播功能）
        try:
            # 尝试发送一个测试广播（使用不存在的 action，只测试命令本身）
            test_result = subprocess.run(
                ["am", "broadcast", "-a", "com.termux.TEST"],
                capture_output=True,
                text=True,
                timeout=3
            )
            # 如果返回码是 0 或 255，或者输出包含 broadcast/Intent 相关，说明命令可用
            if test_result.returncode not in [0, 255] and not any(
                keyword in (test_result.stdout + test_result.stderr).lower() 
                for keyword in ["broadcast", "intent", "component"]
            ):
                if "command not found" in (test_result.stdout + test_result.stderr).lower():
                    return {
                        "status": "error",
                        "data": "am 命令无法执行。请安装: pkg install termux-tools"
                    }
                else:
                    return {
                        "status": "error",
                        "data": "am 命令无法正常工作。Termux bootstrap 的 am 可能功能不完整，请安装: pkg install termux-tools"
                    }
        except Exception:
            # 测试失败，但继续尝试使用
            pass
        
        # 构建广播命令
        cmd = [
            "am", "broadcast",
            "-a", self.ACTION,
            "-n", self.RECEIVER_COMPONENT,
            "--es", "action", action
        ]
        
        # 如果需要返回值，生成result_id并添加到命令中
        result_id = None
        if wait_result:
            result_id = self._generate_result_id()
            cmd.extend(["--es", "result_id", result_id])
        
        # 添加可选参数
        if message is not None:
            cmd.extend(["--es", "message", message])
        if title is not None:
            cmd.extend(["--es", "title", title])
        if data is not None:
            cmd.extend(["--es", "data", data])
        
        # 执行广播命令
        try:
            result = subprocess.run(
                cmd,
                capture_output=True,
                text=True,
                timeout=10  # 命令执行超时
            )
            
            if result.returncode != 0:
                error_msg = result.stderr if result.stderr else "未知错误"
                # 如果返回码是 -6，可能是组件不存在或 am 命令问题
                if result.returncode == -6:
                    error_msg = f"返回码 -6: 组件不存在或 am 命令不可用。请确保：1) 已安装 termux-tools (pkg install termux-tools)，2) 应用包含 PythonApiReceiver 组件"
                return {
                    "status": "error",
                    "data": f"广播命令执行失败 (返回码: {result.returncode}): {error_msg}"
                }
            
            # 如果需要等待返回值
            if wait_result and result_id:
                return self._wait_for_result(result_id, timeout)
            else:
                return None
                
        except subprocess.TimeoutExpired:
            return {
                "status": "error",
                "data": "广播命令执行超时"
            }
        except Exception as e:
            return {
                "status": "error",
                "data": f"执行错误: {e}"
            }
    
    def show_toast(self, message, wait_result=False):
        """
        显示Toast消息
        
        Args:
            message: 要显示的消息
            wait_result: 是否等待返回值
            
        Returns:
            如果wait_result为True，返回结果字典；否则返回None
        """
        return self.call_android("show_toast", message=message, wait_result=wait_result)
    
    def show_notification(self, title, message, wait_result=False):
        """
        显示通知
        
        Args:
            title: 通知标题
            message: 通知内容
            wait_result: 是否等待返回值
            
        Returns:
            如果wait_result为True，返回结果字典；否则返回None
        """
        return self.call_android(
            "notification",
            title=title,
            message=message,
            wait_result=wait_result
        )
    
    def get_device_info(self):
        """
        获取设备信息
        
        Returns:
            dict: 包含status和data的字典，data中包含设备信息字符串
        """
        return self.call_android("get_device_info", wait_result=True)
    
    def calculate(self, expression):
        """
        执行计算（示例）
        
        Args:
            expression: 计算表达式，如 "10+5", "20-3", "6*7", "100/4"
            
        Returns:
            dict: 包含status和data的字典，data中包含计算结果
        """
        return self.call_android("calculate", data=expression, wait_result=True)
    
    def cleanup_old_results(self, max_age_seconds=3600):
        """
        清理旧的结果文件
        
        Args:
            max_age_seconds: 最大保留时间（秒），超过此时间的文件将被删除
        """
        if not os.path.exists(self.result_dir):
            return
        
        current_time = time.time()
        for filename in os.listdir(self.result_dir):
            if filename.endswith('.json'):
                filepath = os.path.join(self.result_dir, filename)
                try:
                    file_age = current_time - os.path.getmtime(filepath)
                    if file_age > max_age_seconds:
                        os.remove(filepath)
                except Exception as e:
                    print(f"清理文件 {filename} 时出错: {e}")


# 便捷函数
def call_android(action, **kwargs):
    """
    便捷函数：调用Android代码
    
    Args:
        action: 要执行的操作
        **kwargs: 其他参数（message, title, data, wait_result, timeout）
        
    Returns:
        结果字典或None
    """
    api = AndroidAPI()
    return api.call_android(action, **kwargs)


if __name__ == "__main__":
    # 测试代码
    print("=" * 60)
    print("Android API 测试")
    print("=" * 60)
    
    api = AndroidAPI()
    
    # 测试1: 获取设备信息（带返回值）
    print("\n1. 测试获取设备信息...")
    result = api.get_device_info()
    if result and result['status'] == 'success':
        print("✓ 成功获取设备信息:")
        print(result['data'])
    else:
        print(f"✗ 失败: {result}")
    
    # 测试2: 执行计算（带返回值）
    print("\n2. 测试执行计算...")
    result = api.calculate("10+5")
    if result and result['status'] == 'success':
        print(f"✓ 计算结果: 10+5 = {result['data']}")
    else:
        print(f"✗ 失败: {result}")
    
    result = api.calculate("20*3")
    if result and result['status'] == 'success':
        print(f"✓ 计算结果: 20*3 = {result['data']}")
    
    # 测试3: 显示Toast（不带返回值）
    print("\n3. 测试显示Toast...")
    api.show_toast("来自Python的测试消息", wait_result=False)
    print("✓ Toast已发送（不等待返回值）")
    
    # 测试4: 显示通知（带返回值）
    print("\n4. 测试显示通知...")
    result = api.show_notification("Python测试", "这是一条测试通知", wait_result=True)
    if result and result['status'] == 'success':
        print(f"✓ {result['data']}")
    
    print("\n" + "=" * 60)
    print("测试完成！")
    print("=" * 60)

    print("\n按 Enter 键退出...")
    try:
        input()
    except (EOFError, KeyboardInterrupt):
        pass

